package com.bc.commonentity.log;

import com.alibaba.dubbo.rpc.RpcContext;
import com.bc.commoncore.config.ConfigBase;
import com.bc.commoncore.security.AES;
import com.bc.commoncore.util.*;
import com.bc.commonentity.common.*;
import com.bc.commonentity.enums.HttpReturnRnums;
import com.bc.commonentity.enums.LogDetailType;
import com.dianping.cat.Cat;
import com.dianping.cat.message.Event;
import com.dianping.cat.message.Transaction;
import com.dianping.cat.message.internal.NullMessage;
import com.dianping.cat.message.spi.MessageTree;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.PhaseInterceptorChain;
import org.apache.cxf.transport.http.AbstractHTTPDestination;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.*;

/**
 * 记录方法调用详情日志的帮助类
 * @author zhaohailong
 * @date 20160627
 */
public class LogDetailHelper {
	private static volatile String sourceSys;
	private static final Logger logger = LoggerFactory.getLogger(LogDetailHelper.class);
	private static synchronized void createSourceSys(){
		if (sourceSys==null) {
			SourceSysBean sourceSysBean=null;
			try {
				sourceSysBean=SpringBeanHelper.getCustomBeanByType(SourceSysBean.class);
			} catch (Exception e) {
				logger.error("SourceSysBean初始化失败"+e.getMessage());
			}
			
			if (sourceSysBean!=null) {
				sourceSys=sourceSysBean.getSourceSys();
			}
		}
	}
	private static String getSourceSys(){
		if (sourceSys==null) {
			createSourceSys();
		}
		return sourceSys==null?"":sourceSys;
	}
	/**
	 * 将异步调用的asynRequestID写入ThreadLocal
	 * 执行重复执行(如果已经存在，则不做任何操作)
	 * 当前线程和主线程一致时才写入asynRequestID
	 * 主线程开始时就会写入requestTime
	 * @author zhaohailong
	 * @date 20160627
	 */
	public static void setAsynRequestInfo(){
		if (AsynLogDetailHolder.getValueFromThreadLocal("requestTime")==null) {
			if (AsynLogDetailHolder.getValueFromThreadLocal("asynRequestID")==null) {
				 AsynLogDetailHolder.setValue2ThreadLocal("asynRequestID", new Date());
			}
		}
	}

	/**
	/**
	 * 生成requestid(为了保证唯一性，用本机ip和uuid的hashcode)
	 * @return
	 * @author zhaohailong
	 * @date 20160627
	 */
	public static Integer getRequestID(){
		return UUID.randomUUID().toString().hashCode(); 
	}
	/**
	 * 从静态变量中获取当然的request对象
	 * @return
	 * @author zhaohailong
	 * @date 20160627
	 */
	public static HttpServletRequest getRequest(){
    	if (RequestContextHolder.getRequestAttributes()!=null) {
    		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    	}
		Message message = PhaseInterceptorChain.getCurrentMessage();
		if (message!=null) {
			Message inMessage = message.getExchange().getInMessage();
			return (HttpServletRequest)inMessage.get(AbstractHTTPDestination.HTTP_REQUEST);
		}
		return null;
    }
	/**
	 * 根据aop切面的args对象获取对应的json参数
	 * @param args
	 * @author zhaohailong
	 * @date 20160725
	 * @return
	 */
	public static String getJsonParam(Object[] args){
		String param="";
		if (args!=null&&args.length>0) {
			List<String> paramList=new ArrayList<>();
			for (Object object : args) {
				if (object==null) {
					continue;
				}
				//HttpServletRequest和HttpServletResponse用json序列号时会报错
				if (object instanceof HttpServletRequest){
					Map<String, String[]> paramMap=((HttpServletRequest)object).getParameterMap();
					if (paramMap!=null&&paramMap.size()>0) {
						paramList.add(JsonUtil.obj2string(paramMap));
						continue;	
					}
				}
				if(object instanceof HttpServletResponse||
						object instanceof InputStream||
						object instanceof OutputStream) {
					continue;
				}
				if (object instanceof String) {
					paramList.add(object.toString());
				}else {
					paramList.add(JsonUtil.obj2string(object));
				}
			}
			if(paramList.size()==1){
				param = paramList.get(0);
	        }else if(args.length > 1){
	        	param = JsonUtil.obj2string(paramList);
	        }
		}
		return param;
	}
	public static Map<String, String> getHeadersInfo(HttpServletRequest request) {
		Map<String, String> map = new HashMap<String, String>();
		Enumeration headerNames = request.getHeaderNames();
		while (headerNames.hasMoreElements()) {
			String key = (String) headerNames.nextElement();
			String value = request.getHeader(key);
			map.put(key, value);
		}
		return map;
	}
/**
 * 根据入参，组装ActionDetailLog对象
 * @param methodName
 * @param parentMethodName
 * @param args
 * @param beginTime
 * @param executeTime
 * @param stackTrace
 * @param sql
 * @param resultJson
 * @param detailType
 * @return
 * @author zhaohailong
 * @date 20160627
 */
	private static ActionDetailLog fillLogDetail(String methodName,String parentMethodName,
    		Object[] args,Date beginTime,
    		long executeTime,String stackTrace,String sql,
    		String resultJson,LogDetailType detailType,Map<String, String> catMessageIdsMap){
		String param =getJsonParam(args);
		List<String> ipinfoList = SystemUtils.getLocalIpInfo();
		String appServerIP = JsonUtil.obj2string(ipinfoList);
		ActionDetailLog log=new ActionDetailLog();
		log.setAppServer(appServerIP);
		log.setSourceSys(getSourceSys());
		log.setExecuteTime(executeTime);
		log.setMethodName(methodName);
		log.setOptType(detailType.value());
		log.setParam(param);
		log.setParentMethodName(parentMethodName);
		log.setBeginTime(0l);
		log.setRequestTime(ParseHelper.ToDateString(beginTime));
		log.setSql(sql);
		//mongo最大单文档为16M，超过这个值时，会保存失败
		//为了保证日志轻量，这里只保存长度小于2000个字符的方法返回值
		resultJson=(resultJson==null?"":resultJson);
		if (resultJson.length()>2000) {
			log.setResultJson("the length of the result is more than 2000,can not show here");
		}else{
			log.setResultJson(resultJson);
		}
		log.setStackTrace(stackTrace);
		if (stackTrace!=null&&!stackTrace.isEmpty()) {
			log.setHasError(1);
		}
		fillCatMessageId(null,log,catMessageIdsMap);
		return log;
	}
	/**
	 * 记录方法调用详情的日志
	 * @param methodName
	 * @param parentMethodName
	 * @param args
	 * @param beginTime
	 * @param executeTime
	 * @param stackTrace
	 * @param sql
	 * @param resultJson
	 * @param detailType
	 * @author zhaohailong
	 * @date 20160627 
	 */
    public static void addLogDetail(String methodName,String parentMethodName,
						    		Object[] args,Date beginTime,
						    		long executeTime,String stackTrace,String sql,
						    		String resultJson,LogDetailType detailType,
									Map<String, String> catMessageIdsMap){
    	try {
    		//如果没开启elk的日志,且当前日志没异常时,则跳过
			if (ConfigBase.getIsOpenMongoLog().equals("0")&&
					StringUtils.isEmpty(stackTrace)) {
				return;
			}
    		//System.out.println("========parentMethodName==============="+parentMethodName);
    		ActionDetailLog logDetail=fillLogDetail( methodName, parentMethodName,
		    				args, beginTime,executeTime, stackTrace, sql,
		    				resultJson, detailType,catMessageIdsMap);
			Date requestTime=AsynLogDetailHolder.getValueFromThreadLocal("requestTime");
			if (requestTime==null) {	//此时表示当前请求为异步请求
				logDetail.setIsAsyn(1);
				List<ActionDetailLog> quartzServiceActionDetialLogList=AsynLogDetailHolder.getValueFromThreadLocal("quartzServiceActionDetialLogList");
				if(quartzServiceActionDetialLogList==null){//普通异步调用
					List<ActionDetailLog> detailLogs=new ArrayList<>();
					detailLogs.add(logDetail);
					LogServiceBLL.SystemActionLog(null, detailLogs);
					return;
				}else{//quartzservice异步调用过来的
					quartzServiceActionDetialLogList.add(logDetail);
					return;
				}
			}else{
				List<ActionDetailLog> actionDetialLogList=AsynLogDetailHolder.getValueFromThreadLocal("actionDetialLogList");
				if (actionDetialLogList!=null) {
					actionDetialLogList.add(logDetail);
				}else{
					List<ActionDetailLog> detialLogs=new ArrayList<>();
					detialLogs.add(logDetail);
					AsynLogDetailHolder.setValue2ThreadLocal("actionDetialLogList",detialLogs);
				}
			}
		} catch (Exception e) {
			logger.error(methodName+"addLogDetail时出错:"+e.getMessage()+StringUtils.getStackTrace(e));
			ErrorEmail.sendErrorMail(methodName+"addLogDetail时出错",e);
		}

    }
    public static void systemActionLog(int userID,String userName,int requestType,
			String clientIp,String url,String param,
			String decryptMsg,String contentType,String header,
			String httpRequestMethod,String methodName,String resultJson,
			String stackTrace,String accessType){
		
		if (contentType==null) {
			contentType="";
		}
		List<String> ipinfoList = SystemUtils.getLocalIpInfo();
		String appServerIP = JsonUtil.obj2string(ipinfoList);
		ActionLog logEngity = new ActionLog();
		logEngity.setUserID(userID);
		logEngity.setUserName(userName);
		logEngity.setRequestType(requestType);
		logEngity.setClientIp(clientIp);
		logEngity.setSourceSys(getSourceSys());
		logEngity.setRequestUrl(url);
		logEngity.setParam(param);
		logEngity.setDecryptMsg(decryptMsg);
		logEngity.setContentType(contentType);
		logEngity.setHeader(header);
		logEngity.setRequestMethod(httpRequestMethod);
		logEngity.setMethodName(methodName);
		logEngity.setResultJson(resultJson);
		logEngity.setAppServer(appServerIP);
		logEngity.setStackTrace(stackTrace);
		if (stackTrace!=null&&!stackTrace.isEmpty()) {
			logEngity.setHasError(1);
		}
		Date endDate = new Date();
		Date requestTime=AsynLogDetailHolder.getValueFromThreadLocal("requestTime");
		if(requestTime==null){
//			logger.error(logEngity.getRequestUrl()+".systemActionLog时出错:requestTime为null");
//			ErrorEmail.sendErrorMail(logEngity.getRequestUrl()+".systemActionLog时出错:requestTime为null",null);
			requestTime=new Date();
		}
		long executeTime=endDate.getTime() - requestTime.getTime();
		logEngity.setExecuteTime(executeTime);
		logEngity.setRequestTime(ParseHelper.ToDateString(requestTime));
		logEngity.setAccessType(accessType);
		fillCatMessageId(logEngity,null,null);
		completeTransaction(logEngity);
		List<ActionDetailLog> detailLogs=AsynLogDetailHolder.getValueFromThreadLocal("actionDetialLogList");
		AsynLogDetailHolder.clearThreadLocal(false);
		LogServiceBLL.SystemActionLog(logEngity,detailLogs);
		logger.debug("方法名称：" + methodName);
		logger.debug("方法入参：" + param);
		logger.debug("方法url:" + url);
		logger.debug("执行时间,精确到毫秒:" + executeTime);
	}
    /**
	 * 从cxf框架的Message对象中获取请求相关的属性
	 * @date 20160217
	 * @author hailongzhao
	 * @return
	 */
	public static ActionLog getQuartzServiceActionLog(){
		Message message = PhaseInterceptorChain.getCurrentMessage();
		Message inMessage = message.getExchange().getInMessage();
		Method methodName = (Method) inMessage.get("org.apache.cxf.resource.method");
		TreeMap header = (TreeMap) inMessage.get(Message.PROTOCOL_HEADERS);
		String contentType = (String) inMessage.get(Message.CONTENT_TYPE);
		String httpRequestMethod = (String) inMessage.get(Message.HTTP_REQUEST_METHOD);
		String url = (String) inMessage.get(Message.REQUEST_URL);
		HttpServletRequest request = (HttpServletRequest)inMessage.get(AbstractHTTPDestination.HTTP_REQUEST);
		String clientIp = SystemUtils.getClientIp(request);
		ActionLog logEngity = new ActionLog();
		logEngity.setClientIp(clientIp);
		logEngity.setRequestUrl(url);
		logEngity.setContentType(contentType);
		logEngity.setHeader(header.toString());
		logEngity.setRequestMethod(httpRequestMethod);
		logEngity.setMethodName(methodName.toString());
		return logEngity;
	}
	/**
	 * 将异步执行的日志写入mq
	 * @date 20160217
	 * @author hailongzhao
	 * @return
	 */
 	private static void quartzServiceWritelog(ActionLog logEngity,
 			String stackTrace,String resultJson){
		try {
			List<String> ipinfoList = SystemUtils.getLocalIpInfo();
			String appServerIP = JsonUtil.obj2string(ipinfoList);
			logEngity.setUserID(-1);
			logEngity.setUserName("");
			logEngity.setRequestType(0);
			logEngity.setSourceSys(getSourceSys());
			logEngity.setParam("");
			logEngity.setDecryptMsg("");
			logEngity.setResultJson(resultJson);
			logEngity.setAppServer(appServerIP);
			logEngity.setStackTrace(stackTrace);
			if (stackTrace!=null&&!stackTrace.isEmpty()) {
				logEngity.setHasError(1);
			}
			Date requestTime=ParseHelper.ToDate(logEngity.getRequestTime());
			Date endDate = new Date();
			logEngity.setExecuteTime(endDate.getTime() - requestTime.getTime());
			fillCatMessageId(logEngity,null,null);
			completeTransaction(logEngity);
			List<ActionDetailLog> detailLogs=AsynLogDetailHolder.getValueFromThreadLocal("quartzServiceActionDetialLogList");
			AsynLogDetailHolder.clearThreadLocal(false);
			LogServiceBLL.SystemActionLog(logEngity,detailLogs);
		} catch (Exception e) {
			logger.error(logEngity.getRequestUrl()+"quartzServiceWritelog时出错:"+e.getMessage()+StringUtils.getStackTrace(e));
			ErrorEmail.sendErrorMail(logEngity.getRequestUrl()+"quartzServiceWritelog时出错",e);
		}

	}
	public static void quartzServiceLogBefore(ActionLog logEngity){
		//防止线程池的情况下threadlocal中的变量被复用
		AsynLogDetailHolder.clearThreadLocal(true);
		logEngity.setRequestTime(ParseHelper.ToDateString(new Date(), ""));
		if (ConfigBase.getIsOpenESLog().equals("0")) {
			return;
		}
		Transaction t=Cat.newTransaction("accessUrl", logEngity.getRequestUrl());
		AsynLogDetailHolder.setValue2ThreadLocal("catTransaction",t);
		AsynLogDetailHolder.setValue2ThreadLocal("quartzServiceActionDetialLogList",new ArrayList<ActionDetailLog>());
	}
	public static void quartzServiceLogAfter(ActionLog logEngity,JsonResult result){
		String stackTrace = "";
		if (result.getCode()!=HttpReturnRnums.Success.value()) {
			stackTrace=result.getMsg()+(result.getData()==null?"":result.getData().toString());
		}
		String resultJson=JsonUtil.obj2string(result);
		quartzServiceWritelog(logEngity,stackTrace,resultJson);
	}

	/**
	 * 如果开启了cat分布式消息树,则给elk的参数赋值mgsid
	 * @param logEngity
	 * @param logDetail
	 * @param catMessageIdsMap
	 */
	private static void fillCatMessageId(ActionLog logEngity,ActionDetailLog logDetail,
										 Map<String, String> catMessageIdsMap){
		if (logEngity!=null) {
			if (ConfigBase.getIsOpenESLog().equals("0")) {
				return;
			}
			MessageTree tree = Cat.getManager().getThreadLocalMessageTree();
			if (tree==null){
				return;
			}
			logEngity.setCatRootMessageId(tree.getRootMessageId());
			logEngity.setCatParentMessageId(tree.getParentMessageId());
			logEngity.setCatChildMessageId(tree.getMessageId());
			logger.debug(String.format("主Transaction的messageid:rootid:%s;parentid:%s;childid:%s",
					logEngity.getCatRootMessageId(),
					logEngity.getCatParentMessageId(),
					logEngity.getCatChildMessageId()
					));
		}else if(logDetail!=null){
			if (catMessageIdsMap==null||catMessageIdsMap.isEmpty()){
				return;
			}
			if (catMessageIdsMap.containsKey(Cat.Context.ROOT)) {
				logDetail.setCatRootMessageId(catMessageIdsMap.get(Cat.Context.ROOT));
			}
			if (catMessageIdsMap.containsKey(Cat.Context.PARENT)) {
				logDetail.setCatParentMessageId(catMessageIdsMap.get(Cat.Context.PARENT));
			}
			if (catMessageIdsMap.containsKey(Cat.Context.CHILD)) {
				logDetail.setCatChildMessageId(catMessageIdsMap.get(Cat.Context.CHILD));
			}
		}
	}
	/**
	 * 从当前请求中获取外部传递过来的catmessageid
	 * @param requestType
	 * @return
	 */
	private static CatContext getCatMessageIdsMapFromRequest(String requestType){
		String catRootMessageId=null;
		String catParentMessageId=null;
		String catChildMessageId=null;
		switch (requestType) {
			case "dubbox":
				if (RpcContext.getContext() != null) {
					catRootMessageId = RpcContext.getContext().getAttachment(Cat.Context.ROOT);
					catParentMessageId = RpcContext.getContext().getAttachment(Cat.Context.PARENT);
					catChildMessageId = RpcContext.getContext().getAttachment(Cat.Context.CHILD);
				}
				break;
			case "cxf":
				Message message = PhaseInterceptorChain.getCurrentMessage();
				if (message != null) {
					Message inMessage = message.getExchange().getInMessage();
					TreeMap header = (TreeMap) inMessage.get(Message.PROTOCOL_HEADERS);
					//由于nginx默认配置下,不允许header中的keyname中包含_,
					//因此从header中获取cat的messageid时,这里的keyname都去掉了_
					if (header.get(Cat.Context.ROOT.substring(1)) != null) {
						catRootMessageId = header.get(Cat.Context.ROOT.substring(1)).toString().replace("[", "").replace("]", "");
					}
					if (header.get(Cat.Context.PARENT.substring(1)) != null) {
						catParentMessageId = header.get(Cat.Context.PARENT.substring(1)).toString().replace("[", "").replace("]", "");
					}
					if (header.get(Cat.Context.CHILD.substring(1)) != null) {
						catChildMessageId = header.get(Cat.Context.CHILD.substring(1)).toString().replace("[", "").replace("]", "");
					}
				}
				break;
			case "springmvc":
				break;
			default:
				break;
		}
		CatContext catContext = new CatContext();
		catContext.addProperty(CatContext.ROOT, catRootMessageId);
		catContext.addProperty(CatContext.PARENT, catParentMessageId);
		catContext.addProperty(CatContext.CHILD, catChildMessageId);
//		logger.debug(String.format("从上级接收到的Transaction的messageid:rootid:%s;parentid:%s;childid:%s",
//				catRootMessageId,
//				catParentMessageId,
//				catChildMessageId
//		));
		return catContext;
	}
	/**
	 * 接收外部传递过来的catmessageid，用于构建cat消息树
	 * @param url
	 * @param requestType
	 */
	public static void initCatMessageTree(String url,String requestType){
		try {
			//防止线程池的情况下threadlocal中的变量被复用
			AsynLogDetailHolder.clearThreadLocal(true);
			if (ConfigBase.getIsOpenESLog().equals("0")) {
				return;
			}
			if(needCheck(url)){
				//ThreadLocal记录相关信息
				AsynLogDetailHolder.setValue2ThreadLocal("requestTime",new Date());
				AsynLogDetailHolder.setValue2ThreadLocal("actionDetialLogList",new ArrayList<ActionDetailLog>());

				String transType="accessUrl";
				if("dubbox".equals(requestType)){
					transType="dubboxAccessUrl";
				}
				Transaction t=Cat.newTransaction(transType, getRequestUrl(url));
				AsynLogDetailHolder.setValue2ThreadLocal("catTransaction",t);
				//构建cat消息树
				CatContext catContext =LogDetailHelper.getCatMessageIdsMapFromRequest(requestType);
				Cat.logRemoteCallServer(catContext);
			}
		}catch (Exception e){
			logger.error(url+"initCatMessageTree时出错:"+e.getMessage()+StringUtils.getStackTrace(e));
			ErrorEmail.sendErrorMail(url+"initCatMessageTree时出错",e);
		}
	}

	/**
	 * 主请求完成时，结束cat的Transaction
	 * @param logEngity
	 */
	private static void completeTransaction(ActionLog logEngity){
		Transaction trans=AsynLogDetailHolder.getValueFromThreadLocal("catTransaction");
		if (trans!=null&&logEngity!=null) {
			if("accessUrl".equals(logEngity.getAccessType())){
				trans.addData("appServerIP",logEngity.getAppServer());
			}
			trans.setStatus(getCauseBy(logEngity,null));
			trans.complete();
		}
	}
	/**
	 * 如果开启了分布式调用链的开关，则调用外部接口时传递catmessageid,用于构建分布式消息树
	 * @param logDetailType
	 */
	public static Map<String, String> setAttachment(LogDetailType logDetailType){
		if(logDetailType!=LogDetailType.dubbox&&logDetailType!=LogDetailType.postget){
			return null;
		}
		CatContext catContext = new CatContext();
		Cat.logRemoteCallClient(catContext);
		Map<String, String> catMessageIdsMap=new HashMap<>();
		catMessageIdsMap.put(CatContext.ROOT, catContext.getProperty(CatContext.ROOT));
		catMessageIdsMap.put(CatContext.PARENT, catContext.getProperty(CatContext.PARENT));
		catMessageIdsMap.put(CatContext.CHILD, catContext.getProperty(CatContext.CHILD));
		if(logDetailType==LogDetailType.dubbox){
			if (RpcContext.getContext()!=null) {
				RpcContext.getContext().setAttachment(Cat.Context.ROOT, catMessageIdsMap.get(Cat.Context.ROOT));
				RpcContext.getContext().setAttachment(Cat.Context.PARENT, catMessageIdsMap.get(Cat.Context.PARENT));
				RpcContext.getContext().setAttachment(Cat.Context.CHILD, catMessageIdsMap.get(Cat.Context.CHILD));
			}
		}else if (logDetailType==LogDetailType.postget) {
			PostAndGetImpl.setCatMessageIdsMap(catMessageIdsMap);
		}
//		logger.debug(String.format("haha;%s;传递给下级Transaction的messageid:rootid:%s;parentid:%s;childid:%s",
//				logDetailType.desc(),
//				catMessageIdsMap.get(Cat.Context.ROOT),
//				catMessageIdsMap.get(Cat.Context.PARENT),
//				catMessageIdsMap.get(Cat.Context.CHILD)
//		));
		return catMessageIdsMap;
	}
	/**
	 * 获取log中的url
	 *
	 * @author houzhangbo
	 * @param log
	 * @return
	 */
	public static String getRequestKey(ActionDetailLog log){
		String objUrl = "";
		if(log.getOptType().intValue()==LogDetailType.postget.value()){//http请求
			if(!StringUtils.isEmpty(log.getParam())){
				if(log.getParam().indexOf("[")>-1){
					List<String> strList = JsonUtil.str2list(log.getParam(), String.class);
					if(null!=strList&&strList.size()>0){
						objUrl = getRequestUrl(strList.get(0));
					}
				}else {
					objUrl = getRequestUrl(log.getParam());
				}
			}
		}else if(log.getOptType().intValue()==LogDetailType.redis.value()){//redis操作
			if(!StringUtils.isEmpty(log.getParam())){
				if(log.getParam().indexOf("[")>-1){//redis下param就是redis的key
					//redis的set操作 param会有多个参数
					List<String> strList = JsonUtil.str2list(log.getParam(), String.class);
					if(null!=strList&&strList.size()>0){
						objUrl = strList.get(0);
					}
				}else{
					//redis的get请求 中param只有一个redis的key
					objUrl = log.getParam();
				}
			}
			if (org.apache.commons.lang.StringUtils.isNotBlank(objUrl)) {
				objUrl=objUrl.replace("\"", "");
			}
		}else{
			objUrl = log.getMethodName();
		}
		return objUrl;
	}
	public static String getRequestUrl(String url){
		if (url!=null&&!url.isEmpty()) {
			int index=url.indexOf("?");
			if (index>0) {
				return url.substring(0, index);
			}
		}
		return url;
	}
	public static String getCauseBy(ActionLog logEngity,String stackTrace){
		if (logEngity!=null&&logEngity.getHasError()==1) {
			if (logEngity.getException()!=null&&
					!logEngity.getException().isEmpty()&&
					!logEngity.getException().equals(HttpReturnRnums.SystemError.desc())) {
				return ParseHelper.filterCauseBy(logEngity.getException());
			}
			return ParseHelper.filterCauseBy(logEngity.getStackTrace());
		}
		if (!StringUtils.isEmpty(stackTrace)) {
			return ParseHelper.filterCauseBy(stackTrace);
		}
		return Transaction.SUCCESS;
	}

	public static boolean needCheck(String url){
		//如果是swagger接口文档请求来的，则不记录日志
		if (url.indexOf("/api-docs")>=0||
				url.indexOf("/alert/heart")>=0||
				url.indexOf("/swagger")>=0||
				url.indexOf("/quartzhttpservice/")>=0) {
			return false;
		}
		return true;
	}

	private static void checkParam(Method method){
		if (method==null) {
			return;
		}
		//先获取方法上的注解
		Consumes consumes=method.getAnnotation(Consumes.class);
		//如果方法上的注解为null，则获取方法所属的类上的注解
		if (consumes==null) {
			consumes=method.getDeclaringClass().getAnnotation(Consumes.class);
		}
		//如果方法所属的类上的注解为null,则取类实现的接口上的注解
		if (consumes==null) {
			Class<?>[] interfaces=method.getDeclaringClass().getInterfaces();
			if (interfaces!=null&&interfaces.length>0) {
				for (Class<?> class1 : interfaces) {
					consumes=class1.getAnnotation(Consumes.class);
					if (consumes!=null) {
						break;
					}
				}
			}
		}
		if (consumes==null||
				consumes.value()==null||
				consumes.value().length==0) {
			throw new RuntimeException("接口或方法必须添加Consumes注解");
		}
		boolean isjson=false;
		for (String item : consumes.value()) {
			if (item.toLowerCase().contains("json")) {
				isjson=true;
				break;
			}
		}
		//只有Consumes为json时，才对入参进行校验
		if (!isjson) {
			return;
		}
		//判断方法的入参有几个
		Class<?>[] parameterTypes = method.getParameterTypes();
		if (parameterTypes==null) {
			return;
		}
		if (parameterTypes.length!=1) {
			throw new RuntimeException("方法入参只能有一个参数");
		}
		if (ParseHelper.isBaseObj(parameterTypes[0])||
				parameterTypes[0]== List.class) {
			throw new RuntimeException("方法入参只能为自定义实体");
		}
		if(method.getReturnType()!=JsonResult.class){
			throw new RuntimeException("方法返回值的类型只能为JsonResult");
		}
	}
	public static void decryptCxfMessageInputStream(Message message,String interceptSwith){
		if(message==null){
			return;
		}
		if(interceptSwith==null){
			interceptSwith="0";
		}
		try {
			Exchange exchange = message.getExchange();
			Message inMessage = exchange.getInMessage();
			Object contentType = inMessage.get(Message.CONTENT_TYPE);
			//如果是图片上传，则直接返回(因为输入流中的内容是二进制流)
			if(contentType!=null&&contentType.toString().contains("multipart/form-data")){
				return;
			}
			InputStream inputStream = message.getContent(InputStream.class);
			String inputMsg = StreamUtils.copyToStringNoclose(inputStream);
			if (inputMsg == null || inputMsg.isEmpty()) {
				return;
			}
			String encryptMsg = inputMsg;
			String decryptMsg = inputMsg;
			logCustomerInfo(message,encryptMsg,decryptMsg);

			if (interceptSwith.equals("1")) {// 开启加密
				logger.debug("已开启解密拦截器");
//				if (inputMsg.indexOf("data") < 0) {
//					throw new RuntimeException("应该传入加密后的入参！");
//				}
				ParameterReq req = JsonUtil.str2obj(inputMsg, ParameterReq.class);
				if(StringUtils.isEmpty(req.getData())){
					throw new RuntimeException("传过来的加密后的data为空");
				}
				encryptMsg = req.getData();
				decryptMsg = AES.aesDecrypt(StringUtils.trimRight(req.getData(), "\n"));// AES解密
				logCustomerInfo(message,encryptMsg,decryptMsg);
			} else {
				logger.debug("暂未开启解密");
//				if (inputMsg.indexOf("data") > 0) {
//					throw new RuntimeException("应该传入未加密的入参");
//				}
			}
			logger.debug("未解密的入参:" + encryptMsg);
			logger.debug("解密后的入参:" + decryptMsg);
//			if (decryptMsg.indexOf("{") < 0 && decryptMsg.indexOf("}") < 0) {
//				throw new RuntimeException("解密后的参数必须是json格式的数据");
//			}
			InputStream stream = StreamUtils.StringToInputStream(decryptMsg);
			message.setContent(InputStream.class, stream);// 回填流
		} catch (Exception e) {
			throw new InterceptorRunTimeException("处理入参时出错:" + e.getMessage()+StringUtils.getStackTrace(e));
		}
	}
	private static void logCustomerInfo(Message message,String encryptMsg,String decryptMsg){
		Exchange exchange = message.getExchange();
		if (exchange.containsKey("encryptMsg")) {
			exchange.remove("encryptMsg");
		}
		if (exchange.containsKey("decryptMsg")) {
			exchange.remove("decryptMsg");
		}

		exchange.put("encryptMsg", encryptMsg);
		exchange.put("decryptMsg", decryptMsg);
	}

	/**
	 * 用于构建cat项目调用关系图
	 * @param t
	 */
	public static void pigeonCall(Transaction t){
		if(t==null||t instanceof NullMessage){
			return;
		}
		String url=t.getName();
		if(url==null||url.isEmpty()){
			return;
		}
		String target="";

		if(url.indexOf("http://javanoticeapi")>=0){
			target="noticeapihttp";
		}else if(url.indexOf("http://javauserapi")>=0){
			target="userapihttp";
		}else if(url.indexOf("http://javaorderapi")>=0){
			target="orderapihttp";
		}else if(url.indexOf("http://javaareaapi")>=0){
			target="areaapihttp";
		}else if(url.indexOf("http://javamarketingapi")>=0||url.indexOf(".marketingcontact.")>0){
			target="marketingapihttp";
		}else if(url.indexOf("http://javagoodsapi")>=0||url.indexOf(".goodscontact.")>0){
			target="goodsapihttp";
		}else if(url.indexOf("http://javaucenterapi")>=0||url.indexOf(".ucentercontact.")>0){
			target="ucenterapihttp";
		}else if(url.indexOf("http://dyapi")>=0||url.indexOf(".dyxpcontact.")>0){
			target="dyxpshophttp";
		}else if(url.indexOf("http://toolsapi")>=0||url.indexOf(".toolscontact.")>0){
			target="toolsapihttp";
		}else if(url.indexOf("http://javaadvertapi")>=0||url.indexOf(".advertcontact.")>0){
			target="advertapihttp";
		}else if(url.indexOf("http://openapimall")>=0||url.indexOf("http://testopenapi")>=0){
			target="mallopenapihttp";
		}else{
			target=getDomain(url);
		}
		Event event=Cat.newEvent("PigeonCall.app",target);
		event.setStatus(Transaction.SUCCESS);
		t.addChild(event);
	}
	private static String getDomain(String url){
		if(url==null||url.trim().isEmpty()){
			return "";
		}
		if(url.startsWith("http://")||
				url.startsWith("https://")||
				url.startsWith("dubbo://")){
			int index=url.indexOf("://")+"://".length();

			String s=url.substring(index);
			int i= s.indexOf("/");
			if(i>0){
				return s.substring(0,i);
			}else{
				return s;
			}
		}
		return url;
	}
}
